package com.msite.util.encrypt

import sun.misc.BASE64Decoder
import sun.misc.BASE64Encoder

import javax.crypto.Cipher
import java.security.*
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec

/**
 * Created by tpeng on 2015/12/2.
 * 基于RSA的数字签名
 */
class Signature {

    /*
    public static final String KEY_ALGORITHM = "DSA";
    public static final String SIGNATURE_ALGORITHM = "DSA";
     */

    public static final String KEY_ALGORTHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static final String DEFAULT_SEED = '$%)aw^*(HJG8%^(fjas7';

    /**
     * BASE64解密
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception{
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64加密
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key)throws Exception{
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * 初始化密钥
     * @return
     * @throws Exception
     */
    public static Map<String,Object> initKey()throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
        //keyPairGenerator.initialize(1024, new SecureRandom(seed: DEFAULT_SEED.bytes ));
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        //公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //私钥
        RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();

        Map<String,Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("RSAPublicKey", publicKey);
        keyMap.put("RSAPrivateKey", privateKey);

        return keyMap;
    }

    /**
     * 取得公钥，并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
        Key key = (Key) keyMap.get("RSAPublicKey");
        return encryptBASE64(key.getEncoded());
    }

    /**
     * 取得私钥，并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
        Key key = (Key) keyMap.get("RSAPrivateKey");
        return encryptBASE64(key.getEncoded());
    }

    /**
     * 用公钥加密
     * @param data  加密数据
     * @param key   密钥
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
        //对公钥解密
        byte[] keyBytes = decryptBASE64(key);
        //取公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    /**
     * 用公钥解密
     * @param data  加密数据
     * @param key   密钥
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
        //对私钥解密
        byte[] keyBytes = decryptBASE64(key);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    /**
     * 用私钥加密
     * @param data  加密数据
     * @param key   密钥
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{
        //解密密钥
        byte[] keyBytes = decryptBASE64(key);
        //取私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        //对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }

    /**
     * 用私钥解密
     * @param data  加密数据
     * @param key   密钥
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
        //对私钥解密
        byte[] keyBytes = decryptBASE64(key);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }


    /**
     *  用私钥对信息生成数字签名
     * @param data  //加密数据
     * @param privateKey    //私钥
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey)throws Exception{
        //解密私钥
        byte[] keyBytes = decryptBASE64(privateKey);
        //构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取私钥匙对象
        PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //用私钥对信息生成数字签名
        java.security.Signature signature = java.security.Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey2);
        signature.update(data);

        return encryptBASE64(signature.sign());
    }

    /**
     * 校验数字签名
     * @param data  加密数据
     * @param publicKey 公钥
     * @param sign  数字签名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data,String publicKey, String sign)throws Exception{
        //解密公钥
        byte[] keyBytes = decryptBASE64(publicKey);
        //构造X509EncodedKeySpec对象
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取公钥匙对象
        PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);

        java.security.Signature signature = java.security.Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey2);
        signature.update(data);
        //验证签名是否正常
        return signature.verify(decryptBASE64(sign));

    }

    public static void main(String[] args) {
        /*def m = Signature.initKey()
        def publicKey = getPublicKey(m)
        def privateKey = getPrivateKey(m)
        println publicKey
        println "---------------------------------"
        println privateKey*/

        /*def sign = sign("d123g4".bytes, "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMaKs+TZCx1CUZDGy/kSVu08QLop\n" +
                "+4coJcinB8fW3YDyYbLDXDm5QScc/sVtaTgu3hSWQa46yMN4b+l5SZ+3PrHrBsGPLETalMvzvRuV\n" +
                "H6WhUOemRsIuLWEMTnMhe64HzUUJ7qX4MZfqS/nuamQLVLXuUG+g9BdZj0KiUzOxWrmfAgMBAAEC\n" +
                "gYBUqIYmuenEUygGjM4i6ZAJXpzXBNnM+vCJi7eEnfkbZ78DA8yKjJTcgb+dHZc1Lr7hlmRxT32V\n" +
                "5AAMVPxwzyk64SitDiWPe4ZJ3xkGEjpGA1GVirCQ2r1aO54Z3ELlFw50OnJRLEu3xYZK+Z8fakpm\n" +
                "lehYIiHdlzcqtHmnyEVIaQJBAPh7/4haTXUkVzqYLCNb3JQPrMlKP7sKuSRm8DbFq38ULNaD/+6C\n" +
                "3V4mamJDYhP0GwDrkoiN08VuGQk4xTlKytUCQQDMjAB3+ClQHWsZzSeNZAiv0VvgXaDARJHRwBZ+\n" +
                "reY6PK2rkxHa/Zy3rbIQ+9wXcSj0T6M4ytDnADYt30cM70SjAkEAtl4zPfygqp/AUWXLxyutaRFU\n" +
                "C+uteHY3SYsvM9PBuSOygMIiPQfYtjfVjkbMHb7jbrp2Mjh9O4JBZ649uX21/QJAaxZ0/FoxDt+H\n" +
                "/ecZaP3RSnMaXdnG2kJL8XtWi5XxrdWsuuHxfCxAyy0lx5yEesVkwpubAZW1Tusecl+t7AisbwJA\n" +
                "Jnx4Kwb2gsKaIEj0Z9ThIk/PNd4v+H+gj1riexK87I4o8AgcieBBR4QqEwv/Ronsmd/E+ebd5Hh9\n" +
                "c5r4nB8ruA==")
        println sign*/

        def t = verify("d123g4".bytes, "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGirPk2QsdQlGQxsv5ElbtPEC6KfuHKCXIpwfH\n" +
                "1t2A8mGyw1w5uUEnHP7FbWk4Lt4UlkGuOsjDeG/peUmftz6x6wbBjyxE2pTL870blR+loVDnpkbC\n" +
                "Li1hDE5zIXuuB81FCe6l+DGX6kv57mpkC1S17lBvoPQXWY9ColMzsVq5nwIDAQAB", "Bi/w/NQtTCHd4ISAhPgQquPUeF+Or9k2kyHe9FFAbMIfVXHP3/bl+OQD7hGALAzPAGS8Rd/anBxY\n" +
                "d7acu5L6UCrV2gKggZjDp0WxouI7GDgrgsDs+7MYN/pnYyxEpqdLrA5+c+7uK3ctxrMInaNrAOS8\n" +
                "eWzhrZGymvh11jos5+s=")
        println t
    }
}
